/*
 * WllCompactCommand.cpp
 *
 *  Created on: 2016-1-1
 *      Author: wll
 */

#include "WllCompactCommand.h"
#include "VariableStack.h"
#include "WllInterpreter.h"
#include "Wll3Interpreter.h"
#include "WllTrace.h"
#include "WllSingleton.h"
#include "WllString.h"
#include "LanguageAlgorithm.h"
#include <iostream>
#include <fstream>
#include <iterator>
#include <cassert>
#include "CompilerManager.h"
#include "IntepretException.h"
#include "Calculate.h"
#include "Utils.h"
using namespace std;
using namespace Wll::Util;

//load SYMBOLS by WllLoader to replace current languages
//$LOAD_TRANSLATION(COMPACT_SYMBOL) => VOID_SYMBOL
bool CompactLoadTranslationCommand::Interpret(std::vector<Symbols>& data_stack)
{
    assert(data_stack.size() >= 1);
    Symbols compacted_symbol = data_stack.back();
    data_stack.pop_back();

    INFO("command=" << Symbols::LOAD_TRANSLATIONS << ", op1=" << compacted_symbol);

    assert(compacted_symbol.type == SymbolTypes::COMPACT_TYPE);

    return LoadLanguage(compacted_symbol.GetList(), interpreter->context.language_grammar, false);
}

//($CLEAR_TRANSLATION)
bool CompactClearTranslationCommand::Interpret(std::vector<Symbols>& data_stack)
{
    INFO("command=" << Symbols::CLEAR_TRANSLATIONS);

    interpreter->context.language_grammar.translation_rules.clear();
    interpreter->context.language_grammar.Initialize();

    INFO("interpreter context language grammar initialized");

    return true;
}

//load SYMBOLS by WllLoader append into current languages
//$ADD_TRANSLATION(COMPACT_SYMBOL) => VOID_SYMBOL
bool CompactAddTranslationCommand::Interpret(std::vector<Symbols>& data_stack)
{
    assert(data_stack.size() >= 1);
    Symbols compacted_symbol = data_stack.back();
    data_stack.pop_back();

    INFO("command=" << Symbols::ADD_TRANSLATIONS << ", op1=" << compacted_symbol);

    assert(compacted_symbol.type == SymbolTypes::COMPACT_TYPE);

    return LoadLanguage(compacted_symbol.GetList(), interpreter->context.language_grammar, true);
}

//($CREATE_COMPILER)
bool CompactCreateCompilerCommand::Interpret(std::vector<Symbols>& data_stack)
{
    INFO("command=" << Symbols::CREATE_COMPILER);

    Compiler* compiler = new Compiler();
    compiler->languages = interpreter->context.language_grammar;
    interpreter->context.compiler = compiler;

    INFO("interpreter context compiler created");

    return true;
}

//compose source_rule(MAP_SYMBOL) and destination_rule(MAP_SYMBOL) as translation, 加载到上下文环境中的compiler_language
//$TRANSLATION(MAP_SYMBOL,MAP_SYMBOL) => MAP_SYMBOL
bool CompactTranslationCommand::Interpret(std::vector<Symbols>& data_stack)
{
    assert(data_stack.size() >= 2);
    Symbols destination_rule = data_stack.back();
    data_stack.pop_back();
    Symbols source_rule = data_stack.back();
    data_stack.pop_back();

    INFO("command=" << Symbols::REMARK_TRANSLATION << ", op1=" << source_rule << ", op2=" << destination_rule);

    assert(source_rule.type == SymbolTypes::MAP_TYPE);
    assert(destination_rule.type == SymbolTypes::MAP_TYPE);

    LanguageTranslations translation(
            LanguageRules(source_rule.GetMap()["root"], source_rule.GetMap()["expression"].GetList()),
            LanguageRules(destination_rule.GetMap()["root"], destination_rule.GetMap()["expression"].GetList())
            );
    interpreter->context.language_grammar.translation_rules.push_back(translation);

    INFO("command=" << Symbols::REMARK_TRANSLATION << ", result=" << translation);

    return true;
}

//compose root_symbol(VARIABLE_SYMBOL) and expression(SYMBOLS) as rule(MAP_SYMBOL)
//$RULE(VARIABLE_SYMBOL,COMPACT_SYMBOL) => MAP_SYMBOL
bool CompactRuleCommand::Interpret(std::vector<Symbols>& data_stack)
{
    assert(data_stack.size() >= 2);
    Symbols expression = data_stack.back();
    data_stack.pop_back();
    Symbols root = data_stack.back();
    data_stack.pop_back();

    INFO("command=" << Symbols::REMARK_RULE << ", op1=" << root << ", op2=" << expression);

    assert(root.IsVariable());
    assert(expression.type == SymbolTypes::COMPACT_TYPE);

    Symbols rule(SymbolTypes::MAP_TYPE);
    rule.GetMap()["root"] = root;
    rule.GetMap()["expression"] = expression;

    data_stack.push_back(rule);

    INFO("command=" << Symbols::REMARK_RULE << ", result=" << rule);

    return true;
}

//($VARIABLE, COMPACT_SYMBOL)
bool CompactVariableCommand::Interpret(std::vector<Symbols>& data_stack)
{
    assert(data_stack.size() >= 1);
    Symbols compacted_symbol = data_stack.back();
    data_stack.pop_back();

    INFO("command=" << Symbols::REMARK_VARIABLE << ", op1=" << compacted_symbol);

    assert(compacted_symbol.type == SymbolTypes::COMPACT_TYPE);
    AssertSymbolsType(compacted_symbol.GetList(), SymbolTypes::CONSTANT_TYPE);

    Symbols variable(compacted_symbol.ToString().c_str());
    data_stack.push_back(variable);

    INFO("command=" << Symbols::REMARK_VARIABLE << ", result=" << variable);

    return true;
}

//compose constants as name of a remark symbol(REMARK_SYMBOL)
//$REMARK(COMPACT_SYMBOL) => VARIABLE_SYMBOL
bool CompactRemarkCommand::Interpret(std::vector<Symbols>& data_stack)
{
    assert(data_stack.size() >= 1);
    Symbols symbol = data_stack.back();
    data_stack.pop_back();

    INFO("command=" << Symbols::REMARK_REMARK << ", op1=" << symbol);

    assert(symbol.type == SymbolTypes::COMPACT_TYPE || symbol.type == SymbolTypes::STRING_TYPE);

    Symbols remark(SymbolTypes::REMARK_TYPE, symbol.ToString().c_str());
    data_stack.push_back(remark);

    INFO("command=" << Symbols::REMARK_REMARK << ", op1=" << remark);

    return true;
}

//evalue symbols' result, whether execute evalue or not is controlled by ignore state
////$EVAL(ANY_SYMBOL) => SYMBOLS(AUTO COMPACT TO COMPACT_SYMBOL)
bool CompactEvalCommand::Interpret(std::vector<Symbols>& data_stack)
{
    assert(data_stack.size() >= 1);
    Symbols symbol = data_stack.back();
    data_stack.pop_back();
    assert(symbol.type == SymbolTypes::COMPACT_TYPE);

    INFO("command=" << Symbols::EVAL << ", op1=" << symbol);

    int size = data_stack.size();
    bool  retval = interpreter->InterpretWllVersion(symbol.GetList(), data_stack);;
    vector<Symbols> result(data_stack.begin()+size, data_stack.end());

    INFO("command=" << Symbols::EVAL << ", result=" << result);

    return retval;   
}

//evalue symbols' result, execute evalue will always do, regardness ignore state
//$EXEC(ANY_SYMBOL) => SYMBOLS(AUTO COMPACT TO COMPACT_SYMBOL)
bool CompactExecCommand::Interpret(std::vector<Symbols>& data_stack)
{
    //SAME AS EVAL COMMAND EXCEPT EXEC TIME
    assert(data_stack.size() >= 1);
    Symbols symbol = data_stack.back();
    data_stack.pop_back();
    assert(symbol.type == SymbolTypes::COMPACT_TYPE);

    INFO("command=" << Symbols::EXEC << ", op1=" << symbol);

    vector<Symbols> result;
    bool retval = interpreter->InterpretWllVersion(symbol.GetList(), result);;
    data_stack += result;

    INFO("command=" << Symbols::EXEC << ", result=" << result);

    return retval;  
}


bool CompactIgnoreCommand::Interpret(std::vector<Symbols>& data_stack)
{
    assert(data_stack.size() >= 1);

    INFO("command=" << Symbols::REMARK_IGNORE <<", op1=" << data_stack.back());
    INFO("command=" << Symbols::REMARK_IGNORE <<", result=" << data_stack.back());

    return true;   
}

//$COMPACT(ANY_SYMBOL,ANY_SYMBOL) => COMPACT_SYMBOL
bool CompactCompactCommand::Interpret(std::vector<Symbols>& data_stack)
{
    assert(data_stack.size() >= 2);
    Symbols data2 = data_stack.back();
    data_stack.pop_back();
    Symbols data1 = data_stack.back();
    data_stack.pop_back();

    INFO("command=" << Symbols::COMPACT <<", op1=" << data1 << ", op2=" << data2);

    Symbols compacted_symbol(SymbolTypes::COMPACT_TYPE);
    Flat(data1, compacted_symbol.GetList());
    Flat(data2, compacted_symbol.GetList());
    data_stack.push_back(compacted_symbol);

    INFO("command=" << Symbols::COMPACT <<", result=" << compacted_symbol);

    return true;   
}


//$LIST ($LIST, A, B, ... , N, n) = (A, B, ... , N)
//$LIST(ANY_SYMBOL, ... , ANY_SYMBOL, n) = S_EXP_SYMBOL
bool CompactListCommand::Interpret(std::vector<Symbols>& data_stack)
{
	assert(data_stack.size() >= 1);
	Symbols n = data_stack.back();
	data_stack.pop_back();

	INFO("command=" << Symbols::LIST <<", op1=" << n);

	assert(n.type == SymbolTypes::INTEGER_TYPE);
	assert(data_stack.size() >= n.i);

	Symbols list(SymbolTypes::S_EXP_TYPE);
	list.GetList().resize(n.i);
	for(vector<Symbols>::reverse_iterator i = list.GetList().rbegin(); i != list.GetList().rend(); i++)
	{
		*i = data_stack.back();
		INFO("pop list element=" << *i);
		data_stack.pop_back();
	}
	data_stack.push_back(list);

	INFO("command=" << Symbols::LIST <<", result=" << list);

	return true;
}

//$APPEND(S_EXP_SYMBOL, S_EXP_SYMBOL) = S_EXP_SYMBOL
//($APPEND, (A,B), (C,D)) = (A, B, C, D)
bool CompactAppendCommand::Interpret(std::vector<Symbols>& data_stack)
{
	assert(data_stack.size() >= 2);
	Symbols tail_list = data_stack.back();
	data_stack.pop_back();
	Symbols head_list = data_stack.back();
	data_stack.pop_back();

	INFO("command=" << Symbols::APPEND <<", op1=" << head_list << ", op2=" << tail_list);

	assert(head_list.type == SymbolTypes::S_EXP_TYPE);
	assert(tail_list.type == SymbolTypes::S_EXP_TYPE);

	Symbols list(head_list);
	list.GetList() += tail_list.GetList();
	data_stack.push_back(list);

	INFO("command=" << Symbols::APPEND << ", result=" << list);

	return true;
}

//$CAR(ANY_SYMBOL) = S_EXP_SYMBOL|NIL
//($CAR, (A,B,C)) = A
bool CompactCarCommand::Interpret(std::vector<Symbols>& data_stack)
{
	assert(data_stack.size() >= 1);
	Symbols symbol = data_stack.back();
	data_stack.pop_back();

	INFO("command=" << Symbols::CAR << ", op1=" << symbol);

	Symbols result;
	if ((symbol.type == SymbolTypes::S_EXP_TYPE || symbol.type == SymbolTypes::COMPACT_TYPE) && (symbol.GetList().size() > 0))
	{
		result = symbol.GetList().front();
	}
	else if (symbol.type == SymbolTypes::STRING_TYPE && (*symbol.s)->size() > 0)
	{
		result = Symbols(SymbolTypes::CONSTANT_TYPE, (*symbol.s)->front());
	}
	else
	{
		result = Symbols(SymbolTypes::COMPACT_TYPE);
	}
	data_stack.push_back(result);

	INFO("command=" << Symbols::CAR << ", result=" << result);

	return true;
}

//$CDR(ANY_SYMBOL) = S_EXP_SYMBOL|NIL
//($CDR, (A,B,C)) = (B, C)
bool CompactCdrCommand::Interpret(std::vector<Symbols>& data_stack)
{
	assert(data_stack.size() >= 1);
	Symbols symbol = data_stack.back();
	data_stack.pop_back();

	INFO("command=" << Symbols::CDR << ", op1=" << symbol);

	Symbols result;
	if ((symbol.type == SymbolTypes::S_EXP_TYPE || symbol.type == SymbolTypes::COMPACT_TYPE) && (symbol.GetList().size() > 1))
	{
		result = Symbols(symbol.type, vector<Symbols>(symbol.GetList().begin()+1, symbol.GetList().end()));
	}
	else if (symbol.type == SymbolTypes::STRING_TYPE && (*symbol.s)->size() > 0)
	{
		(*(*symbol.s)) = (*symbol.s)->substr(1);
		result = symbol;
	}
	else
	{
		result = Symbols(SymbolTypes::COMPACT_TYPE);
	}
	data_stack.push_back(result);

	return true;
}

//$COND(TRUE|FALSE, COMPACT_SYMBOL|S_EXP_SYMBOL)
//($COND, CONDITION, THEN, ELSE)
bool CompactCondCommand::Interpret(std::vector<Symbols>& data_stack)
{
	assert(data_stack.size() >= 3);
	Symbols else_part = data_stack.back();
	data_stack.pop_back();
	Symbols then_part = data_stack.back();
	data_stack.pop_back();
	Symbols condition = data_stack.back();
	data_stack.pop_back();

	INFO("command=" << Symbols::COND << ", condition=" << condition << ", then_part=" << then_part << ", else_part=" << else_part);

	vector<Symbols>::iterator begin = data_stack.end();
	if (condition == Symbols::TRUE)
	{
		if (then_part.type == SymbolTypes::COMPACT_TYPE || then_part.type == SymbolTypes::S_EXP_TYPE)
		{
            interpreter->InterpretWllVersion(then_part.GetList(), data_stack);
		}
		else
		{
			data_stack.push_back(then_part);
		}
	}
	else
	{
		if (else_part.type == SymbolTypes::COMPACT_TYPE || else_part.type == SymbolTypes::S_EXP_TYPE)
		{
            interpreter->InterpretWllVersion(else_part.GetList(), data_stack);
		}
		else
		{
			data_stack.push_back(else_part);
		}
	}
	vector<Symbols> result(begin, data_stack.end());

	INFO("command=" << Symbols::COND << ", result=" << result);
	
	return true;
}


//$LOOP(COMPACT,COMPACT)
//($LOOP, CONDITION, REPEAT)
bool CompactLoopCommand::Interpret(std::vector<Symbols>& data_stack)
{
	assert(data_stack.size() >= 2);
	Symbols repeat = data_stack.back();
	data_stack.pop_back();
	Symbols condition = data_stack.back();
	data_stack.pop_back();

	INFO("command=" << Symbols::LOOP << ", condition=" << condition << ", repeat=" << repeat);

	assert(repeat.type == SymbolTypes::COMPACT_TYPE || repeat.type == SymbolTypes::S_EXP_TYPE);

	vector<Symbols>::iterator r = data_stack.end();
	do
	{
		Symbols condition_result;
		if (condition.type == SymbolTypes::COMPACT_TYPE || condition.type == SymbolTypes::S_EXP_TYPE)
		{
            interpreter->InterpretWllVersion(condition.GetList(), data_stack);
			condition_result = data_stack.back();
			data_stack.pop_back();
		}
		else
		{
			condition_result = condition;
		}
		
		if (!(condition_result == Symbols::TRUE)) break;

        interpreter->InterpretWllVersion(repeat.GetList(), data_stack);
	} while (true);

    //TODO:拷贝构造和析构存在未知bug
    //vector<Symbols> result(r,data_stack.end());
	//INFO("command=" << Symbols::LOOP << ", result=" << result);

	return true;
}

//$CALL(VARIABLE_SYMBOL,COMPACT_SYMBOL)
//($CALL, VARIABLE_SYMBOL, COMPACT_SYMBOL) => COMPACT_SYMBOL
bool CompactCallCommand::Interpret(std::vector<Symbols>& data_stack)
{
	assert(data_stack.size() >= 2);
	Symbols input_symbols = data_stack.back();
	data_stack.pop_back();
	Symbols start_symbol = data_stack.back();
	data_stack.pop_back();

	INFO("command=" << Symbols::CALL << ", start_symbol=" << start_symbol << ", input_symbols=" << input_symbols);

	assert(input_symbols.type == SymbolTypes::COMPACT_TYPE);
	assert(start_symbol.type == SymbolTypes::VARIABLE_TYPE);

	vector<Symbols> result;
    ArraySymbolsFlow arraySymbolsFlow(input_symbols.GetList());
	bool retval = interpreter->compiler->Process(arraySymbolsFlow, result, start_symbol, TOTAL_MODE);
	if (retval)
	{
		data_stack += result;
	}
    retval = true;
	
	INFO("command=" << Symbols::CALL << ", result=" << result);

	return retval;
}

//$FCALL(STRING_SYMBOL,VARIABLE_SYMBOL,COMPACT_SYMBOL)
//($FCALL, STRING_SYMBOL, VARIABLE_SYMBOL, COMPACT_SYMBOL) => COMPACT_SYMBOL
bool CompactFCallCommand::Interpret(std::vector<Symbols>& data_stack)
{
	assert(data_stack.size() >= 3);
	Symbols input_symbols = data_stack.back();
	data_stack.pop_back();
	Symbols start_symbol = data_stack.back();
	data_stack.pop_back();
	Symbols file_name = data_stack.back();
	data_stack.pop_back();

	INFO("command=" << Symbols::FCALL << ", file_name=" << file_name << ", start_symbol=" << start_symbol << ", input_symbols=" << input_symbols);

	assert(input_symbols.type == SymbolTypes::COMPACT_TYPE);
	assert(start_symbol.type == SymbolTypes::VARIABLE_TYPE);
	assert(file_name.type == SymbolTypes::STRING_TYPE);
	
	vector<Symbols> result;
	Compiler* compiler = Singleton<CompilerManager>().GetInstance()->CreateOrGetCompiler(**file_name.s);
	ArraySymbolsFlow arraySymbolsFlow(input_symbols.GetList());
    bool retval = compiler->Process(arraySymbolsFlow, result, start_symbol, TOTAL_MODE);
	if (retval)
	{
        data_stack += result;
	}
    retval = true;

	INFO("command=" << Symbols::FCALL << ", result=" << result);

	return retval;
}

Symbols* Index(Symbols* symbol, string index, bool write_flag=false)
{	
	assert(symbol != NULL);

	if(symbol->type == SymbolTypes::LIST_TYPE)
	{
		int index_i;
		String2Int(index,index_i);
		if(index_i == symbol->GetList().size())
		{
			if(write_flag)
			{
				symbol->GetList().resize(index_i+1);
			}
			else
			{
				throw IntepretException("read index["+index+"] out of range");
			}
		}
		else if(index_i > symbol->GetList().size() || index_i < 0)
		{
			throw IntepretException("index["+index+"] out of range");
			//throw IntepretException((write_flag?string("write"):string("read"))+" index["+index+"] out of range"); 
		}
		symbol = &(symbol->GetList()[index_i]);
	}
	else if(symbol->type == SymbolTypes::MAP_TYPE)
	{
		if (write_flag) 
		{
			symbol = &(symbol->GetMap()[index]);
		}
		else
		{
			symbol = &(symbol->GetMap().at(index));
		}		
	}
	else
	{
		throw IntepretException("index with type other than LIST and MAP");
	}		

	return symbol;
}

//$REF(REFERENCE,STRING)
bool CompactLRefCommand::Interpret(std::vector<Symbols>& data_stack)
{
	assert(data_stack.size() >= 1);
	Symbols symbol = data_stack.back();
	data_stack.pop_back();

	INFO("command=" << Symbols::LREF << ", op1=" << symbol);

	assert(symbol.type == SymbolTypes::STRING_TYPE || symbol.type == SymbolTypes::COMPACT_TYPE || symbol.type == SymbolTypes::REFERENCE_TYPE);

	Symbols result((Symbols*)(NULL));
	if (symbol.type == SymbolTypes::STRING_TYPE || symbol.type == SymbolTypes::COMPACT_TYPE)
	{
		VariableStack* variable_table_stack = interpreter->context.GetVariableTableStack();
		assert(!variable_table_stack->empty());
		result.reference = variable_table_stack->LookupOrRegister(symbol.ToString());
	}
	else if (symbol.type == SymbolTypes::REFERENCE_TYPE)
	{
		assert(data_stack.size() >= 1);
		Symbols index = data_stack.back();
		data_stack.pop_back();
		assert(index.type == SymbolTypes::STRING_TYPE || index.type == SymbolTypes::COMPACT_TYPE || index.type == SymbolTypes::INTEGER_TYPE || index.type == SymbolTypes::LONG_TYPE);
		result.reference = Index(symbol.reference, index.ToString(), true);
	}
	data_stack.push_back(result);

	INFO("command=" << Symbols::LREF << ", result=" << result);
	
	return true;
}

//$RREF(REFERENCE,STRING)
bool CompactRRefCommand::Interpret(std::vector<Symbols>& data_stack)
{
	assert(data_stack.size() >= 1);
	Symbols symbol = data_stack.back();
	data_stack.pop_back();

	INFO("command=" << Symbols::RREF << ", op1=" << symbol);

	assert(symbol.type == SymbolTypes::STRING_TYPE || symbol.type == SymbolTypes::COMPACT_TYPE || symbol.type == SymbolTypes::REFERENCE_TYPE);

	Symbols result;
	result.type = SymbolTypes::REFERENCE_TYPE;
	if (symbol.type == SymbolTypes::STRING_TYPE || symbol.type == SymbolTypes::COMPACT_TYPE)
	{
		VariableStack* variable_table_stack = interpreter->context.GetVariableTableStack();
		assert(!variable_table_stack->empty());
		result.reference = variable_table_stack->Lookup(symbol.ToString());
	}
	else if (symbol.type == SymbolTypes::REFERENCE_TYPE)
	{
		assert(data_stack.size() >= 1);
		Symbols index = data_stack.back();
		data_stack.pop_back();
		assert(index.type == SymbolTypes::STRING_TYPE || index.type == SymbolTypes::COMPACT_TYPE || index.type == SymbolTypes::INTEGER_TYPE || index.type == SymbolTypes::LONG_TYPE);
		result.reference = Index(symbol.reference, index.ToString(), false);
	}
	data_stack.push_back(result);

	INFO("command=" << Symbols::RREF << ", result=" << result);
	
	return true;
}

//$DEF(STRING, ANY_SYMBOL)
bool CompactDefCommand::Interpret(std::vector<Symbols>& data_stack)
{
	assert(data_stack.size() >= 2);
	Symbols value = data_stack.back();
	data_stack.pop_back();
	Symbols symbol = data_stack.back();
	data_stack.pop_back();

	INFO("command=" << Symbols::DEF << ", symbol=" << symbol << ", value=" << value);

	assert(symbol.type == SymbolTypes::STRING_TYPE || symbol.type == SymbolTypes::COMPACT_TYPE);
	string id = symbol.ToString();

	VariableStack* variable_table_stack = interpreter->context.GetVariableTableStack();
	assert(!variable_table_stack->empty());
	Symbols* reference_symbol = variable_table_stack->Register(id);
	*reference_symbol = value;
	
	return true;
}

//$SET(STRING|REFERENCE, ANY_SYMBOL)
bool CompactSetCommand::Interpret(std::vector<Symbols>& data_stack)
{
	assert(data_stack.size() >= 2);
	Symbols value = data_stack.back();
	data_stack.pop_back();
	Symbols symbol = data_stack.back();
	data_stack.pop_back();

	INFO("command=" << Symbols::SET << ", symbol=" << symbol << ", value=" << value);

	assert(symbol.type == SymbolTypes::STRING_TYPE || symbol.type == SymbolTypes::COMPACT_TYPE || symbol.type == SymbolTypes::REFERENCE_TYPE);

	if (symbol.type == SymbolTypes::STRING_TYPE || symbol.type == SymbolTypes::COMPACT_TYPE)
	{
		string id = symbol.ToString();
		VariableStack* variable_table_stack = interpreter->context.GetVariableTableStack();
		assert(!variable_table_stack->empty());
		Symbols* reference_symbol = variable_table_stack->LookupOrRegister(id);
		*reference_symbol = value;
	} 
	else if (symbol.type == SymbolTypes::REFERENCE_TYPE)
	{
		assert(symbol.reference != NULL);
		*symbol.reference = value;
	}
	
	return true;
}

//$GET(STRING|REFERENCE, ANY_SYMBOL)
bool CompactGetCommand::Interpret(std::vector<Symbols>& data_stack)
{
	assert(data_stack.size() >= 1);
	Symbols symbol = data_stack.back();
	data_stack.pop_back();

	INFO("command=" << Symbols::GET << ", symbol=" << symbol);

	assert(symbol.type == SymbolTypes::STRING_TYPE || symbol.type == SymbolTypes::COMPACT_TYPE || symbol.type == SymbolTypes::REFERENCE_TYPE);

	if (symbol.type == SymbolTypes::STRING_TYPE || symbol.type == SymbolTypes::COMPACT_TYPE)
	{
		string id = symbol.ToString();
		VariableStack* variable_table_stack = interpreter->context.GetVariableTableStack();
		assert(!variable_table_stack->empty());
		Symbols* reference_symbol = variable_table_stack->Lookup(id);
		assert(reference_symbol != NULL);
		data_stack.push_back(*reference_symbol);
		INFO("command=" << Symbols::GET << ", result=" << *reference_symbol);	
	}
	else if (symbol.type == SymbolTypes::REFERENCE_TYPE)
	{
		assert(symbol.reference != NULL);
		data_stack.push_back(*symbol.reference);
		INFO("command=" << Symbols::GET << ", result=" << *symbol.reference);
	}

	return true;
}

//$PUSHDATA()
//($PUSHDATA)
bool CompactPushDataCommand::Interpret(std::vector<Symbols>& data_stack)
{
	VariableStack* variable_table_stack = interpreter->context.GetVariableTableStack();
	variable_table_stack->Push();

	INFO("command=" << Symbols::PUSH_DATA << ", variable_table_stack size=" << variable_table_stack->size());

	return true;
}

//$POPDATA()
//($POPDATA)
bool CompactPopDataCommand::Interpret(std::vector<Symbols>& data_stack)
{
	VariableStack* variable_table_stack = interpreter->context.GetVariableTableStack();
	assert(!variable_table_stack->empty());
	variable_table_stack->Pop();

	INFO("command=" << Symbols::POP_DATA << ", variable_table_stack size=" << variable_table_stack->size());

	return true;
}

//$PUSH
bool CompactPushCommand::Interpret(std::vector<Symbols>& data_stack)
{
	//vector<Symbols>*parameter_stack = interpreter->context.GetParameterStack();
	Symbols symbol = data_stack.back();
	//data_stack.pop_back();

	INFO("command=" << Symbols::PUSH << ", symbol=" << symbol);

	//parameter_stack->push_back(symbol);

	return true;
}

//$POP(STRING_SYMBOL|REFERENCE)
bool CompactPopCommand::Interpret(std::vector<Symbols>& data_stack)
{
	//vector<Symbols>*parameter_stack = interpreter->context.GetParameterStack();
	//assert(!parameter_stack->empty());

	assert(data_stack.size() >= 1);
	Symbols symbol = data_stack.back();
	data_stack.pop_back();

	INFO("command=" << Symbols::POP << ", symbol=" << symbol);

	assert(symbol.type == SymbolTypes::STRING_TYPE || symbol.type == SymbolTypes::REFERENCE_TYPE);

	if (symbol.type == SymbolTypes::STRING_TYPE)
	{
		VariableStack* variable_table_stack = interpreter->context.GetVariableTableStack();
		assert(!variable_table_stack->empty());
		Symbols* reference_symbol = variable_table_stack->LookupOrRegister(*(*(symbol.s)));
		*reference_symbol = data_stack.back();
		data_stack.pop_back();
		INFO("command=" << Symbols::POP << ", value=" << *reference_symbol);	
	}
	else if (symbol.type == SymbolTypes::REFERENCE_TYPE)
	{
		assert(symbol.reference != NULL);
		*symbol.reference = data_stack.back();
		data_stack.pop_back();
		INFO("command=" << Symbols::POP << ", value=" << *symbol.reference);
	}
	
	return true;
}

//$ARRAY()
//($ARRAY)
bool CompactArrayCommand::Interpret(std::vector<Symbols>& data_stack)
{
	Symbols symbol(SymbolTypes::LIST_TYPE);
	data_stack.push_back(symbol);

	INFO("command=" << Symbols::ARRAY << ", result=" << symbol);

	return true;
}

//$MAP()
//($MAP)
bool CompactMapCommand::Interpret(std::vector<Symbols>& data_stack)
{
	Symbols symbol(SymbolTypes::MAP_TYPE);
	data_stack.push_back(symbol);

	INFO("command=" << Symbols::MAP << ", result=" << symbol);

	return true;
}

//$SYMBOL(type,value)
bool CompactSymbolCommand::Interpret(std::vector<Symbols>& data_stack)
{
    assert(data_stack.size() >= 2);
    Symbols value = data_stack.back();
    data_stack.pop_back();
    Symbols type = data_stack.back();
    data_stack.pop_back();

    INFO("command=" << Symbols::SYMBOL << ", type=" << type << ", value=" << value);

    assert(type.type == SymbolTypes::COMPACT_TYPE || type.type == SymbolTypes::STRING_TYPE);
    assert(type.type == SymbolTypes::COMPACT_TYPE || type.type == SymbolTypes::STRING_TYPE);

    Symbols result = Symbols(type.ToString().c_str(), value.ToString().c_str());
    data_stack.push_back(result);

    INFO("command=" << Symbols::SYMBOL << ", result=" << result);

    return true;
}

//$CAST(REMARK_SYMBOL,SYMBOL)
bool CompactCastCommand::Interpret(std::vector<Symbols>& data_stack)
{
	assert(data_stack.size() >= 2);
	Symbols value = data_stack.back();
	data_stack.pop_back();
	Symbols type = data_stack.back();
	data_stack.pop_back();

	INFO("command=" << Symbols::CAST << ", type=" << type << ", value=" << value);

	assert(type.IsRemark());
    
	Symbols result = CastTo(type, value);	
	data_stack.push_back(result);

	INFO("command=" << Symbols::CAST << ", result=" << result);

	return true;
}

//($ADD, SYMBOLS, SYMBOLS) = SYMBOLS + SYMBOLS
bool CompactAddCommand::Interpret(std::vector<Symbols>& data_stack)
{
	assert(data_stack.size() >= 2);
	Symbols n2 = data_stack.back();
	data_stack.pop_back();
	Symbols n1 = data_stack.back();
	data_stack.pop_back();

	INFO("command=" << Symbols::ADD << ", n1=" << n1 << ", n2=" << n2);

	assert(
		n1.type == SymbolTypes::CHAR_TYPE ||
		n1.type == SymbolTypes::INTEGER_TYPE ||
		n1.type == SymbolTypes::LONG_TYPE ||
		n1.type == SymbolTypes::FLOAT_TYPE ||
		n1.type == SymbolTypes::DOUBLE_TYPE ||
		n1.type == SymbolTypes::COMPACT_TYPE
	);
	assert(
		n2.type == SymbolTypes::CHAR_TYPE ||
		n2.type == SymbolTypes::INTEGER_TYPE ||
		n2.type == SymbolTypes::LONG_TYPE ||
		n2.type == SymbolTypes::FLOAT_TYPE ||
		n2.type == SymbolTypes::DOUBLE_TYPE ||
		n2.type == SymbolTypes::COMPACT_TYPE
	);	

	if (n1.type == SymbolTypes::COMPACT_TYPE)
	{
		n1 = CastTo(n1.GetList(), true);
	}
	if (n2.type == SymbolTypes::COMPACT_TYPE)
	{
		n2 = CastTo(n2.GetList(), true);
	}	
	AddTo(n1, n2);
	data_stack.push_back(n1);

	INFO("command=" << Symbols::ADD << ", result=" << n1);

	return true;
}

//($SUB, SYMBOLS, SYMBOLS) = SYMBOLS - SYMBOLS
bool CompactSubCommand::Interpret(std::vector<Symbols>& data_stack)
{
	assert(data_stack.size() >= 2);
	Symbols n2 = data_stack.back();
	data_stack.pop_back();
	Symbols n1 = data_stack.back();
	data_stack.pop_back();

	INFO("command=" << Symbols::SUB << ", n1=" << n1 << ", n2=" << n2);

	assert(
		n1.type == SymbolTypes::CHAR_TYPE ||
		n1.type == SymbolTypes::INTEGER_TYPE ||
		n1.type == SymbolTypes::LONG_TYPE ||
		n1.type == SymbolTypes::FLOAT_TYPE ||
		n1.type == SymbolTypes::DOUBLE_TYPE ||
		n1.type == SymbolTypes::COMPACT_TYPE
	);
	assert(
		n2.type == SymbolTypes::CHAR_TYPE ||
		n2.type == SymbolTypes::INTEGER_TYPE ||
		n2.type == SymbolTypes::LONG_TYPE ||
		n2.type == SymbolTypes::FLOAT_TYPE ||
		n2.type == SymbolTypes::DOUBLE_TYPE ||
		n2.type == SymbolTypes::COMPACT_TYPE
	);	

	if (n1.type == SymbolTypes::COMPACT_TYPE)
	{
		n1 = CastTo(n1.GetList(), true);
	}
	if (n2.type == SymbolTypes::COMPACT_TYPE)
	{
		n2 = CastTo(n2.GetList(), true);
	}	
	n1 -= n2;
	data_stack.push_back(n1);

	INFO("command=" << Symbols::SUB << ", result=" << n1);

	return true;
}

//($MUL, SYMBOLS, SYMBOLS) = SYMBOLS * SYMBOLS
bool CompactMulCommand::Interpret(std::vector<Symbols>& data_stack)
{
	assert(data_stack.size() >= 2);
	Symbols n2 = data_stack.back();
	data_stack.pop_back();
	Symbols n1 = data_stack.back();
	data_stack.pop_back();

	INFO("command=" << Symbols::MUL << ", n1=" << n1 << ", n2=" << n2);

	assert(
		n1.type == SymbolTypes::CHAR_TYPE ||
		n1.type == SymbolTypes::INTEGER_TYPE ||
		n1.type == SymbolTypes::LONG_TYPE ||
		n1.type == SymbolTypes::FLOAT_TYPE ||
		n1.type == SymbolTypes::DOUBLE_TYPE ||
		n1.type == SymbolTypes::COMPACT_TYPE
	);
	assert(
		n2.type == SymbolTypes::CHAR_TYPE ||
		n2.type == SymbolTypes::INTEGER_TYPE ||
		n2.type == SymbolTypes::LONG_TYPE ||
		n2.type == SymbolTypes::FLOAT_TYPE ||
		n2.type == SymbolTypes::DOUBLE_TYPE ||
		n2.type == SymbolTypes::COMPACT_TYPE
	);	

	if (n1.type == SymbolTypes::COMPACT_TYPE)
	{
		n1 = CastTo(n1.GetList(), true);
	}
	if (n2.type == SymbolTypes::COMPACT_TYPE)
	{
		n2 = CastTo(n2.GetList(), true);
	}	
	n1 *= n2;
	data_stack.push_back(n1);

	INFO("command=" << Symbols::MUL << ", result=" << n1);

	return true;
}

//($DIV, SYMBOLS, SYMBOLS) = SYMBOLS / SYMBOLS
bool CompactDivCommand::Interpret(std::vector<Symbols>& data_stack)
{
	assert(data_stack.size() >= 2);
	Symbols n2 = data_stack.back();
	data_stack.pop_back();
	Symbols n1 = data_stack.back();
	data_stack.pop_back();

	INFO("command=" << Symbols::DIV << ", n1=" << n1 << ", n2=" << n2);

	assert(
		n1.type == SymbolTypes::CHAR_TYPE ||
		n1.type == SymbolTypes::INTEGER_TYPE ||
		n1.type == SymbolTypes::LONG_TYPE ||
		n1.type == SymbolTypes::FLOAT_TYPE ||
		n1.type == SymbolTypes::DOUBLE_TYPE ||
		n1.type == SymbolTypes::COMPACT_TYPE
	);
	assert(
		n2.type == SymbolTypes::CHAR_TYPE ||
		n2.type == SymbolTypes::INTEGER_TYPE ||
		n2.type == SymbolTypes::LONG_TYPE ||
		n2.type == SymbolTypes::FLOAT_TYPE ||
		n2.type == SymbolTypes::DOUBLE_TYPE ||
		n2.type == SymbolTypes::COMPACT_TYPE
	);	

	if (n1.type == SymbolTypes::COMPACT_TYPE)
	{
		n1 = CastTo(n1.GetList(), true);
	}
	if (n2.type == SymbolTypes::COMPACT_TYPE)
	{
		n2 = CastTo(n2.GetList(), true);
	}	
	n1 /= n2;
	data_stack.push_back(n1);

	INFO("command=" << Symbols::DIV << ", result=" << n1);

	return true;
}

//($SAME, SYMBOL, SYMBOL)
bool CompactSameCommand::Interpret(std::vector<Symbols>& data_stack)
{
	assert(data_stack.size() >= 2);
	Symbols n2 = data_stack.back();
	data_stack.pop_back();
	Symbols n1 = data_stack.back();
	data_stack.pop_back();

	INFO("command=" << Symbols::SAME << ", n1=" << n1 << ", n2=" << n2);

	Symbols result = (n1==n2) ? Symbols::TRUE : Symbols::FALSE;
	data_stack.push_back(result);

	INFO("command=" << Symbols::SAME << ", result=" << result);

	return true;
}

//($EQ, CHAR_SYMBOL|INTEGER_SYMBOL|LONG_SYMBOL|FLOAT_SYMBOL|DOUBLE_SYMBOL|COMPACT_SYMBOL, SYMBOL)
bool CompactEqCommand::Interpret(std::vector<Symbols>& data_stack)
{
	assert(data_stack.size() >= 2);
	Symbols n2 = data_stack.back();
	data_stack.pop_back();
	Symbols n1 = data_stack.back();
	data_stack.pop_back();

	INFO("command=" << Symbols::EQ << ", n1=" << n1 << ", n2=" << n2);

	assert(
		n1.type == SymbolTypes::CHAR_TYPE ||
		n1.type == SymbolTypes::INTEGER_TYPE ||
		n1.type == SymbolTypes::LONG_TYPE ||
		n1.type == SymbolTypes::FLOAT_TYPE ||
		n1.type == SymbolTypes::DOUBLE_TYPE ||
		n1.type == SymbolTypes::COMPACT_TYPE
	);
	assert(
		n2.type == SymbolTypes::CHAR_TYPE ||
		n2.type == SymbolTypes::INTEGER_TYPE ||
		n2.type == SymbolTypes::LONG_TYPE ||
		n2.type == SymbolTypes::FLOAT_TYPE ||
		n2.type == SymbolTypes::DOUBLE_TYPE ||
		n2.type == SymbolTypes::COMPACT_TYPE
	);

	if (n1.type == SymbolTypes::COMPACT_TYPE)
	{
		n1 = CastTo(n1.GetList(), true);
	}
	if (n2.type == SymbolTypes::COMPACT_TYPE)
	{
		n2 = CastTo(n2.GetList(), true);
	}
	Symbols result = Equal(n1, n2) ? Symbols::TRUE : Symbols::FALSE;
	data_stack.push_back(result);

	INFO("command=" << Symbols::EQ << ", result=" << result);

	return true;
}

//($LT, CHAR_SYMBOL|INTEGER_SYMBOL|LONG_SYMBOL|FLOAT_SYMBOL|DOUBLE_SYMBOL|COMPACT_SYMBOL, SYMBOL)
bool CompactLtCommand::Interpret(std::vector<Symbols>& data_stack)
{
	assert(data_stack.size() >= 2);
	Symbols n2 = data_stack.back();
	data_stack.pop_back();
	Symbols n1 = data_stack.back();
	data_stack.pop_back();

	INFO("command=" << Symbols::LT << ", n1=" << n1 << ", n2=" << n2);

	assert(
		n1.type == SymbolTypes::CHAR_TYPE ||
		n1.type == SymbolTypes::INTEGER_TYPE ||
		n1.type == SymbolTypes::LONG_TYPE ||
		n1.type == SymbolTypes::FLOAT_TYPE ||
		n1.type == SymbolTypes::DOUBLE_TYPE ||
		n1.type == SymbolTypes::COMPACT_TYPE
	);
	assert(
		n2.type == SymbolTypes::CHAR_TYPE ||
		n2.type == SymbolTypes::INTEGER_TYPE ||
		n2.type == SymbolTypes::LONG_TYPE ||
		n2.type == SymbolTypes::FLOAT_TYPE ||
		n2.type == SymbolTypes::DOUBLE_TYPE ||
		n2.type == SymbolTypes::COMPACT_TYPE
	);

	if (n1.type == SymbolTypes::COMPACT_TYPE)
	{
		n1 = CastTo(n1.GetList(), true);
	}
	if (n2.type == SymbolTypes::COMPACT_TYPE)
	{
		n2 = CastTo(n2.GetList(), true);
	}
	Symbols result = LessThan(n1, n2) ? Symbols::TRUE : Symbols::FALSE;
	data_stack.push_back(result);

	INFO("command=" << Symbols::LT << ", result=" << result);

	return true;
}

//$AND(TRUE|FALSE, TRUE|FALSE)
bool CompactAndCommand::Interpret(std::vector<Symbols>& data_stack)
{
	assert(data_stack.size() >= 2);
	Symbols b2 = data_stack.back();
	data_stack.pop_back();
	Symbols b1 = data_stack.back();
	data_stack.pop_back();

	INFO("command=" << Symbols::AND << ", b1=" << b1 << ", b2=" << b2);

	assert(b1 == Symbols::TRUE || b1 == Symbols::FALSE);
	assert(b2 == Symbols::TRUE || b2 == Symbols::FALSE);

	Symbols result = (b1 == Symbols::TRUE && b2 == Symbols::TRUE) ? Symbols::TRUE : Symbols::FALSE;
	data_stack.push_back(result);

	INFO("command=" << Symbols::AND << ", result=" << result);
	
	return true;
}

//$OR(TRUE|FALSE, TRUE|FALSE)
bool CompactOrCommand::Interpret(std::vector<Symbols>& data_stack)
{
	assert(data_stack.size() >= 2);
	Symbols b2 = data_stack.back();
	data_stack.pop_back();
	Symbols b1 = data_stack.back();
	data_stack.pop_back();

	INFO("command=" << Symbols::OR << ", b1=" << b1 << ", b2=" << b2);

	assert(b1 == Symbols::TRUE || b1 == Symbols::FALSE);
	assert(b2 == Symbols::TRUE || b2 == Symbols::FALSE);

	Symbols result = (b1 == Symbols::TRUE || b2 == Symbols::TRUE) ? Symbols::TRUE : Symbols::FALSE;
	data_stack.push_back(result);

	INFO("command=" << Symbols::OR << ", result=" << result);
	
	return true;
}

//$NOT(TRUE|FALSE, TRUE|FALSE)
bool CompactNotCommand::Interpret(std::vector<Symbols>& data_stack)
{
	assert(data_stack.size() >= 1);
	Symbols b1 = data_stack.back();
	data_stack.pop_back();

	INFO("command=" << Symbols::NOT << ", b1=" << b1);

	assert(b1 == Symbols::TRUE || b1 == Symbols::FALSE);

	Symbols result = (b1 == Symbols::FALSE) ? Symbols::TRUE : Symbols::FALSE;
	data_stack.push_back(result);

	INFO("command=" << Symbols::NOT << ", result=" << result);
	
	return true;
}

//$SHELL(STRING_SYMBOL) => STRING_SYMBOL
bool CompactShellCommand::Interpret(std::vector<Symbols>& data_stack)
{
	assert(data_stack.size() >= 1);
	Symbols input_symbol = data_stack.back();
	data_stack.pop_back();

	INFO("command=" << Symbols::SHELL << ", input_symbol=" << input_symbol);

	assert(input_symbol.type == SymbolTypes::STRING_TYPE || input_symbol.type == SymbolTypes::COMPACT_TYPE);

	string input = input_symbol.ToString();
	FILE* fp = popen(input.c_str(),"r");
	if(fp==NULL)
	{
		ERROR("popen failed");
		return false;
	}
	string output;
	char c;
	while((c=fgetc(fp))!=EOF)
	{
		output.push_back(c);
	}
	if(pclose(fp)!=0)
	{
		ERROR("pclose failed");
		return false;;
	}
	Symbols result = Symbols(SymbolTypes::STRING_TYPE, output.c_str());
	data_stack.push_back(result);

	INFO("command=" << Symbols::SHELL << ", result=" << result);

	return true;;
}

//$CAT(STRING_SYMBOL) => COMPACT_SYMBOL
bool CompactCatCommand::Interpret(std::vector<Symbols>& data_stack)
{
	assert(data_stack.size() >= 1);
	Symbols s = data_stack.back();
	data_stack.pop_back();

	INFO("command=" << Symbols::CAT << ", file_name=" << s);

	assert(s.type == SymbolTypes::STRING_TYPE);

	//($CAT, "<file_name>")
	//char* libxyz_path = getenv("LIBXYZ");
    string libxyz_path = string(GetProcessDir()) + "/../data/libxyz";
	string file_name = FindFile(**s.s, libxyz_path);
	if (file_name.empty())
	{
		ERROR("include file [" << **s.s << "] NOT found");
	}

	ifstream input_file(file_name.c_str());
	if(input_file.fail()) 
	{
		ERROR("open file_name" << file_name << " failed!!!");
		return false;
	}
	vector<Symbols> result;
	input_file>>result;
	data_stack.push_back(Encode(result,true));

	INFO("command=" << Symbols::CAT << ", result="<<result);

	return true;
}

//$SUBSTR(STRING) => STRING
bool CompactSubStrCommand::Interpret(std::vector<Symbols>& data_stack)
{
	assert(data_stack.size() >= 3);
	Symbols len = data_stack.back();
	data_stack.pop_back();
	Symbols from = data_stack.back();
	data_stack.pop_back();
	Symbols str = data_stack.back();
	data_stack.pop_back();

	INFO("command=" << Symbols::SUB_STR << ", str=" << str << ", from=" << from << ", len=" << len);

	assert(len.type == SymbolTypes::INTEGER_TYPE);
	assert(from.type == SymbolTypes::INTEGER_TYPE);
	assert(str.type == SymbolTypes::STRING_TYPE);

	**str.s = (*str.s)->substr(from.i, len.i);
	data_stack.push_back(str);

	INFO("command=" << Symbols::SUB_STR << ", result="<<str);

	return true;
}

Command* WllCompactCommandFactory::CreateCommand(const Symbols& command, WllInterpreter* interpreter)
{
	assert(command.IsRemark());

    INFO("IntepretCommand : command = " + command.ToString());

	if (command == Symbols::LOAD_TRANSLATIONS)
	{
		return new CompactLoadTranslationCommand(command, interpreter);
	}
    else if (command == Symbols::CLEAR_TRANSLATIONS)
    {
        return new CompactClearTranslationCommand(command, interpreter);
    }
	else if (command == Symbols::ADD_TRANSLATIONS)
	{
        return new CompactAddTranslationCommand(command, interpreter);
	}
    else if (command == Symbols::CREATE_COMPILER)
    {
        return new CompactCreateCompilerCommand(command, interpreter);
    }
	else if (command == Symbols::REMARK_TRANSLATION)
	{
        return new CompactTranslationCommand(command, interpreter);
	}
	else if (command == Symbols::REMARK_RULE)
	{
        return new CompactRuleCommand(command, interpreter);
	}
	else if (command == Symbols::REMARK_VARIABLE)
	{
        return new CompactVariableCommand(command, interpreter);
	}
	else if (command == Symbols::REMARK_REMARK)
	{
        return new CompactRemarkCommand(command, interpreter);
	}
	else if (command == Symbols::EVAL)
	{
        return new CompactEvalCommand(command, interpreter);
	}
	else if (command == Symbols::EXEC)
	{
        return new CompactExecCommand(command, interpreter);
	}
	else if (command == Symbols::REMARK_IGNORE)
	{
        return new CompactIgnoreCommand(command, interpreter);
	}
	else if (command == Symbols::COMPACT)
	{
        return new CompactCompactCommand(command, interpreter);
	}
	else if (command == Symbols::LIST)
	{
        return new CompactListCommand(command, interpreter);
	}
	else if (command == Symbols::APPEND)
	{
        return new CompactAppendCommand(command, interpreter);
	}
	else if (command == Symbols::CAR)
	{
        return new CompactCarCommand(command, interpreter);
	}
	else if (command == Symbols::CDR)
	{
        return new CompactCdrCommand(command, interpreter);
	}
	else if (command == Symbols::COND)
	{
        return new CompactCondCommand(command, interpreter);
	}
	else if (command == Symbols::LOOP)
	{
        return new CompactLoopCommand(command, interpreter);
	}
	else if (command == Symbols::CALL)
	{
        return new CompactCallCommand(command, interpreter);
	}
	else if (command == Symbols::FCALL)
	{
        return new CompactFCallCommand(command, interpreter);
	}
	else if (command == Symbols::LREF)
	{
        return new CompactLRefCommand(command, interpreter);
	}
	else if (command == Symbols::RREF)
	{
        return new CompactRRefCommand(command, interpreter);
	}
	else if (command == Symbols::DEF)
	{
        return new CompactDefCommand(command, interpreter);
	}
	else if (command == Symbols::SET)
	{
        return new CompactSetCommand(command, interpreter);
	}
	else if (command == Symbols::GET)
	{
        return new CompactGetCommand(command, interpreter);
	}
	else if (command == Symbols::PUSH_DATA)
	{
        return new CompactPushDataCommand(command, interpreter);
	}
	else if (command == Symbols::POP_DATA)
	{
        return new CompactPopDataCommand(command, interpreter);
	}
	else if (command == Symbols::PUSH)
	{
        return new CompactPushCommand(command, interpreter);
	}
	else if (command == Symbols::POP)
	{
        return new CompactPopCommand(command, interpreter);
	}
	else if (command == Symbols::ARRAY)
	{
        return new CompactArrayCommand(command, interpreter);
	}
	else if (command == Symbols::MAP)
	{
        return new CompactMapCommand(command, interpreter);
	}
    else if (command == Symbols::SYMBOL)
    {
        return new CompactSymbolCommand(command, interpreter);
    }
	else if (command == Symbols::CAST)
	{
        return new CompactCastCommand(command, interpreter);
	}
	else if (command == Symbols::ADD)
	{
        return new CompactAddCommand(command, interpreter);
	}
	else if (command == Symbols::SUB)
	{
        return new CompactSubCommand(command, interpreter);
	}
	else if (command == Symbols::MUL)
	{
        return new CompactMulCommand(command, interpreter);
	}
	else if (command == Symbols::DIV)
	{
        return new CompactDivCommand(command, interpreter);
	}
	else if (command == Symbols::EQ)
	{
        return new CompactEqCommand(command, interpreter);
	}
	else if (command == Symbols::SAME)
	{
        return new CompactSameCommand(command, interpreter);
	}	
	else if (command == Symbols::LT)
	{
        return new CompactLtCommand(command, interpreter);
	}
	else if (command == Symbols::AND)
	{
        return new CompactAndCommand(command, interpreter);
	}
	else if (command == Symbols::OR)
	{
        return new CompactOrCommand(command, interpreter);
	}
	else if (command == Symbols::NOT)
	{
        return new CompactNotCommand(command, interpreter);
	}
	else if (command == Symbols::SHELL)
	{
        return new CompactShellCommand(command, interpreter);
	}
	else if (command == Symbols::CAT)
	{
        return new CompactCatCommand(command, interpreter);
	}
	else if (command == Symbols::SUB_STR)
	{
        return new CompactSubStrCommand(command, interpreter);
	}

	return nullptr;
}


